﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using TunnelsOfDeath.Objects;
using Microsoft.Xna.Framework;

namespace TunnelsOfDeath.LoadSave
{
    class MapLoader
    {

        XDocument mapsData;

        public MapLoader(string _name)
        {
            mapsData = XDocument.Load(_name + ".xml");
        }

        public void LoadFirstMap()
        {
            LoadMap(mapsData.Element("Maps").Element("Map").Attribute("Name").Value);
        }

        public void LoadMap(string _name)
        {
            Globals.PositionUpdate.Clear();
            Globals.Animated.Clear();
            foreach (XElement item in mapsData.Element("Maps").Elements("Map"))
            {
                if (item.Attribute("Name")!=null && item.Attribute("Name").Value == _name)
                {
                    Globals.CurrentMapName = item.Attribute("Name").Value;
                    SetProperMapsize(item);

                    int x = 0;
                    int y = 0;

                    foreach (XElement column in item.Elements("Column"))
                    {
                        foreach (XElement field in column.Elements("Field"))
                        {
                            SetMapField(x, y, field);
                            x++;
                        }
                        y++;
                        x = 0;
                    }


                }
            }

        }

        private void SetMapField(int x, int y, XElement field)
        {
            Sprite toAdd = null;
            Vector2 position = new Vector2(x,y);

            switch (field.Value)
            {
                case "wall":
                    toAdd = Globals.MainGenerator.GetWall(position);
                    break;
                case "dirt":
                    toAdd = Globals.MainGenerator.GetDirt(position);
                    break;
                case "player":
                    toAdd = FillPlayer(position, field);
                    break;
                case "empty":
                    toAdd = null;
                    break;
                case "gold":
                    toAdd = Globals.MainGenerator.GetGold(position);
                    break;
                case "door":
                    toAdd = FillDoor(position, field);
                    break;
                case "enemy":
                    toAdd = FillEnemy(position, field);
                    break;
                case "rock":
                    toAdd = Globals.MainGenerator.GetRock(position);
                    break;

                default:
                    break;
            }

            Globals.ObjectManager.RegisterObject(toAdd);
        }

        private Door FillDoor(Vector2 _position, XElement _field)
        {
            Door toAdd = null;
            int gold = 0;

            if (_field.Attribute("Needed") != null)
            {
                gold = int.Parse(_field.Attribute("Needed").Value);
            }

            toAdd = Globals.MainGenerator.GetDoor(_position, gold);
            return toAdd;
        }

        private Enemy FillEnemy(Vector2 _position, XElement _field)
        {
            Enemy toAdd = null;
            bool turn = false;
            short delay = 1;

            if (_field.Attribute("RightTurn") != null)
            {
                turn = bool.Parse(_field.Attribute("RightTurn").Value);
            }

            if (_field.Attribute("Delay") != null)
            {
                delay = short.Parse(_field.Attribute("Delay").Value);
            }

            toAdd = Globals.MainGenerator.GetEnemy(_position, turn, delay);

            return toAdd;
        }

        private Player FillPlayer(Vector2 _position, XElement _field)
        {
            Player _toAdd = null;
            int index = 1;
            if (_field.Attribute("Index") != null)
                index = int.Parse(_field.Attribute("Index").Value);
            
            if (index == 1)
            {
                Generator aaa = Globals.MainGenerator;
                _toAdd = Globals.MainGenerator.GetPlayer(_position, Globals.MainPlayer.Controller, 1);
            } else if (index == 2)
            {
                ControllerSource contr;

                if (Globals.MainPlayer.Controller == ControllerSource.KEYBOARD)
                {
                    contr = ControllerSource.GAMEPAD1;
                }
                else
                {
                    contr = ControllerSource.KEYBOARD;
                }

                _toAdd = Globals.MainGenerator.GetPlayer(_position, contr, 2);

            }

            return _toAdd;

        }

        private void SetProperMapsize(XElement _map)
        {
            int x = 0;
            int y = 0;

            foreach (XElement column in _map.Elements("Column"))
            {
                y++;
                int mx = 0;
                foreach (XElement pos in column.Elements("Field"))
                {
                    mx++;
                }
                if (mx > x)
                    x = mx;

            }

            Globals.Map = new Sprite[x, y];

        }

        public string GetNameOfNextMap(string _name)
        {
            string nextName = "";
            bool found = false;
            foreach (XElement item in mapsData.Element("Maps").Elements("Map"))
            {

                if (found)
                {
                    nextName = item.Attribute("Name").Value;
                    break;
                }

                if (item.Attribute("Name") != null && item.Attribute("Name").Value == _name)
                {
                    found = true;
                        
                }
            }

            return nextName;
        }

    }
}
